/**
 * 编译顶点着色器和片元着色器
 * @param {*} gl 
 * @param {*} type 
 * @param {*} source 
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLShader
 */
export function loadShader(gl, type, source) {
    // Compiles either a shader of type gl.VERTEX_SHADER or gl.FRAGMENT_SHADER
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) && !gl.isContextLost()) {
        const info = gl.getShaderInfoLog(shader);
        gl.deleteShader(shader);
        throw "Could not compile WebGL program. \n\n" + info;
        return null;
    }
    return shader;
}

/**
 * 
 * @param {*} gl 
 * @param {*} vertexSource 
 * @param {*} fragmentSource 
 */
export function createProgram(gl, vertexSource, fragmentSource) {
    const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vertexSource);
    if (!vertexShader) {
        return null;
    }

    const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
    if (!fragmentShader) {
        return null;
    }

    const program = gl.createProgram();

    // 添加预先存在的着色器
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    // https://www.khronos.org/webgl/wiki/HandlingContextLost#Handling_Shaders_and_Programs
    if (!gl.getProgramParameter(program, gl.LINK_STATUS) && !gl.isContextLost()) {
        var info = gl.getProgramInfoLog(program);
        gl.deleteProgram(program);
        throw 'WebGL program 不能编译. \n\n' + info;
        return null;
    }
    gl.deleteShader(vertexShader);
    gl.deleteShader(fragmentShader);
    return program;
}